import { reactive } from 'vue'
import { isEmpty, cloneDeep, pick } from 'lodash'

export default function useMultiSpec() {
  // 默认的sku字段属性
  const defaultColumns = [
    {
      title: '预览图',
      dataIndex: 'image',
      width: 90,
      slotName: 'image'
    },
    {
      title: '商品价格',
      dataIndex: 'goods_price',
      width: 120,
      slotName: 'goods_price'
    },
    {
      title: '划线价格',
      dataIndex: 'line_price',
      width: 120,
      slotName: 'line_price'
    },
    {
      title: '库存数量',
      dataIndex: 'stock_num',
      width: 120,
      slotName: 'stock_num'
    },
    {
      title: '商品重量 (KG)',
      dataIndex: 'goods_weight',
      width: 150,
      slotName: 'goods_weight'
    },
    {
      title: 'SKU编码',
      dataIndex: 'goods_sku_no',
      width: 140,
      slotName: 'goods_sku_no'
    }
  ]

  // 默认的sku记录值
  const defaultSkuItemData = {
    image_id: null,
    image: {},
    goods_price: null,
    line_price: null,
    stock_num: null,
    goods_weight: null,
    goods_sku_no: null
  }

  const multiSpecData = reactive({
    // 规格列表
    specList: [],
    skuColumns: cloneDeep(defaultColumns),
    // SKU列表
    skuList: [],
    // 批量设置sku
    skuBatchForm: cloneDeep(defaultSkuItemData)
  })

  let rowspans = []

  /**
   * 过滤对象的空元素
   * (仅支持一维对象)
   * @param {object} object 源对象
   * @returns {object}
   */
  function getFilterObject(object) {
    const newObj = {}
    for (const key in object) {
      const value = object[key]
      if (!isEmpty(value)) {
        newObj[key] = value
      }
    }
    return newObj
  }

  // 生成sku表格字段名
  function buildSkuColumns() {
    const specList = multiSpecData.specList
    const newColumns = defaultColumns.concat()
    // 遍历规格组整理字段
    for (let specIndex = specList.length; specIndex > 0; specIndex--) {
      const specGroupItem = specList[specIndex - 1]
      newColumns.unshift({
        title: specGroupItem.spec_name,
        dataIndex: `spec_value_${specIndex - 1}`,
        width: 120
      })
    }
    multiSpecData.skuColumns = newColumns
  }

  // 合并已存在的sku数据
  function oldSkuList(newSkuList) {
    const oldSkuList = multiSpecData.skuList.concat()
    if (!oldSkuList.length || !newSkuList.length) {
      return newSkuList
    }
    for (const index in newSkuList) {
      // 查找符合的旧记录
      let oldSkuItem = {}
      if (oldSkuList.length === newSkuList.length) {
        oldSkuItem = cloneDeep(oldSkuList[index])
      } else {
        oldSkuItem = oldSkuList.find(item => item.tempId === newSkuList[index].tempId)
      }
      // 写入新纪录
      if (oldSkuItem) {
        newSkuList[index] = {
          ...newSkuList[index],
          ...pick(oldSkuItem, Object.keys(defaultSkuItemData))
        }
      }
    }
    return newSkuList
  }
  // 生成skuList
  function buildSkuList(cartesianList) {
    const newSkuList = []
    for (let i = 0; i < cartesianList.length; i++) {
      const newSkuItem = {
        ...defaultSkuItemData,
        key: i,
        // tempId用于合并旧记录
        tempId: cartesianList[i].map(item => item.spec_value).join('_'),
        // skuKeys用于传参给后端
        skuKeys: cartesianList[i].map(item => {
          return {
            groupKey: item.groupKey,
            valueKey: item.key
          }
        })
      }
      cartesianList[i].forEach((val, idx) => {
        newSkuItem[`spec_value_${idx}`] = val.spec_value
      })
      newSkuList.push(newSkuItem)
    }
    // 兼容旧的sku数据
    multiSpecData.skuList = oldSkuList(newSkuList)
  }

  // 整理所有的规格
  function specGroupArr() {
    const arrs = []
    multiSpecData.specList.forEach(specGroup => {
      const itemArr = []
      specGroup.valueList.forEach(value => {
        itemArr.push(value)
      })
      arrs.push(itemArr)
    })
    return arrs
  }

  function onUpdate() {
    // 整理所有的规格组
    const specs = specGroupArr()
    // sku记录的规格属性集(生成笛卡尔积)
    const cartesianList = cartesianProductOf(specs)
    // 生成sku字段名
    buildSkuColumns()
    // 生成sku列表数据
    buildSkuList(cartesianList)
    // 计算合并的单元格行数
    mergeRowspan()
  }

  function mergeRowspan() {
    rowspans = []
    let len = multiSpecData.skuList.length
    for (let i = 0; i < multiSpecData.specList.length; i++) {
      rowspans[i] = parseInt(len / multiSpecData.specList[i].valueList.length)
      len = rowspans[i]
    }
  }

  /**
   * 合并单元格
   * 1. 规格组的第一组的有几个规格值第一列就只有几行, 其他规格组超出的需要合并行
   * 2. 当有三组规格组时, 合并第一列和第二列下行的单元格
   * 3. 行数的计算规则: 下一组的函数等于上一组的规格值数量 * 2, 比如:
   * 第一组规格值2个, 渲染2行; 第二组规格值也是3个, 渲染函数时第二组就要渲染 2 * 3, 第三组规格值也是3个, 渲染函数时第三组就要渲染 2 * 3 * 3
   * 4. rowIndex第一行开始计算是否要合并单元格
   * @returns { rowspan?: number; colspan?: number }
   */
  function mergeCells({ rowIndex, columnIndex }) {
    const len = rowspans.length
    if (columnIndex > len) {
      return
    }
    const rowspan = rowspans[columnIndex]
    if (((rowIndex + 1) % rowspan) === 1) {
      return { rowspan: rowspan }
    }
  };

  return {
    defaultSkuItemData,
    multiSpecData,
    getFilterObject,
    onUpdate,
    mergeCells
  }
}

/**
  * 生成笛卡尔积数据
  * cartesianProductOf([arr1, arr2, arr3 ...])
  */
export const cartesianProductOf = arrays => {
  if (!arrays.length) {
    return []
  }
  return Array.prototype.reduce.call(arrays, (arr1, arr2) => {
    var ret = []
    arr1.forEach(v1 => {
      arr2.forEach(v2 => {
        ret.push(v1.concat([v2]))
      })
    })
    return ret
  }, [[]])
}
